﻿using System.Diagnostics;
using System.Text.Json;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using ORS.OrderRobot.IOC;
using ORS.OrderRobot.Service.Helper;
using ORS.OrderRobot.ServiceContracts;
using ORS.OrderRobot.ServiceContracts.Dtos;
using ORS.OrderRobot.ServiceContracts.Dtos.Api;
using ORS.OrderRobot.ServiceContracts.ThridPartApi;

namespace ORS.OrderRobot.Service.ThridPartApi
{
	public class ThirdBasketService: IThirdBasketService,ISingleton
    {
        private readonly IHttpHelper _httpHelper;
        private readonly ILogger<ThirdBasketService> _logger;
        private readonly IHubContext<MessageHub> _hubContext;
        public ThirdBasketService(
            IHttpHelper httpHelper,
            ILogger<ThirdBasketService> logger,
            IHubContext<MessageHub> hubContext
        )
		{
            _httpHelper = httpHelper;
            _logger = logger;
            _hubContext = hubContext;
		}

        public async Task<BasketDto?> AddProductToBasket(ShoppingInput input, CommonInput commonInput)
        {
            // if(input.Cart.First().product_id == "2215100085")
            // {
            //     var mockData = new BasketDto() {
            //         BasketId = commonInput.BasketId,
            //     };
            //     await Task.CompletedTask;
            //     return mockData;
            // }

            var timeWatch = new Stopwatch();
            timeWatch.Start();

            var url = $"/baskets/{commonInput.BasketId}/items";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
                Body = input.Cart
            };
            var httpResult = await _httpHelper.SendAndParseAsync<BasketDto>(url, HttpMethod.Post,requestInfo);
            timeWatch.Stop();
            _logger.LogInformation($"购物车接口执行完成,用时:{timeWatch.ElapsedMilliseconds}ms");
            if (httpResult.StatusCode != 200)
            {
                await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = input.Email, Action = $"添加购物车失败,商品:{input.ProductName}", UsedTime = timeWatch.ElapsedMilliseconds, Type = Consts.ErrMsg });
                _logger.LogError("商品添加到购物车失败。时间:{time},用户:{email},购物车请求:{orderData}",DateTime.Now.China(), commonInput.Email,JsonSerializer.Serialize(input));
                throw new CodeException(httpResult.StatusCode,httpResult.RawContent);
            }
            await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = input.Email, Action = $"添加购物车成功,商品:{input.ProductName}",UsedTime = timeWatch.ElapsedMilliseconds });
            return httpResult.Body;
        }

        public async Task SetFlight(DepatureInput input, CommonInput commonInput)
        {
            var timeWatch = new Stopwatch();
            timeWatch.Start();

            var url = $"/baskets/{commonInput.BasketId}";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
                Body = new
                {
                    c_flightDetails = JsonSerializer.Serialize(input)
                }
            };
            var httpResult = await _httpHelper.SendAsync(url, HttpMethod.Patch, requestInfo);

            timeWatch.Stop();
            _logger.LogInformation($"{commonInput.Email}:设置航班接口执行完成,用时:{timeWatch.ElapsedMilliseconds}ms");
            if (httpResult.StatusCode != 200)
            {
                _logger.LogError("设置航班失败。接口时长:{time},用户:{email},参数:{input}", timeWatch.ElapsedMilliseconds, commonInput.Email, JsonSerializer.Serialize(input));
                throw new CodeException(httpResult.StatusCode, httpResult.RawContent);
            }
        }

        public async Task SetShipments(ShipmentInput input, CommonInput commonInput)
        {
            if (!input.shipping_address.phone.StartsWith("+86 "))
            {
                input.shipping_address.phone = $"+86 {input.shipping_address.phone}";
            }
            var timeWatch = new Stopwatch();
            timeWatch.Start();

            var url = $"/baskets/{commonInput.BasketId}/shipments/me";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
                Body = input
            };
            var httpResult = await _httpHelper.SendAsync(url, HttpMethod.Patch, requestInfo);

            timeWatch.Stop();
            _logger.LogInformation($"{commonInput.Email}:设置收货地址接口执行完成,用时:{timeWatch.ElapsedMilliseconds}ms");
            if (httpResult.StatusCode != 200)
            {
                _logger.LogError("设置收货地址失败。时长:{time},用户:{email},参数:{input}",timeWatch.ElapsedMilliseconds, commonInput.Email, JsonSerializer.Serialize(input));
                throw new CodeException(httpResult.StatusCode, httpResult.RawContent);
            }
        }

        public async Task SetBillingAddress(BillingAddressInput input, CommonInput commonInput)
        {
            if (!input.phone.StartsWith("+86 "))
            {
                input.phone = $"+86 {input.phone}";
            }
            var timeWatch = new Stopwatch();
            timeWatch.Start();

            var url = $"/baskets/{commonInput.BasketId}/billing_address";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
                Body = input
            };

            var httpResult = await _httpHelper.SendAsync(url, HttpMethod.Put, requestInfo);

            timeWatch.Stop();
            _logger.LogInformation($"{commonInput.Email}:设置账单地址请求结束,用时:{timeWatch.ElapsedMilliseconds}ms");
            if (httpResult.StatusCode != 200)
            {
                _logger.LogError("设置账单地址失败。时长:{time},用户:{email},参数:{input}", timeWatch.ElapsedMilliseconds, commonInput.Email, JsonSerializer.Serialize(input));
                throw new CodeException(httpResult.StatusCode, httpResult.RawContent);
            }
        }
        /// <summary>
        /// 设置支付方式
        /// </summary>
        /// <param name="input"></param>
        /// <param name="commonInput"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task SetPayment(PaymentInput input, CommonInput commonInput)
        {
            var timeWatch = new Stopwatch();
            timeWatch.Start();

            var url = $"/baskets/{commonInput.BasketId}/payment_instruments";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
                Body = input
            };
            var httpResult = await _httpHelper.SendAsync(url, HttpMethod.Post, requestInfo);
            timeWatch.Stop();
            _logger.LogInformation($"{commonInput.Email}:设置支付方式接口结束,用时:{timeWatch.ElapsedMilliseconds}ms");
            if (httpResult.StatusCode != 200)
            {
                _logger.LogError("设置支付方式失败。时长:{time},用户:{email},参数:{input}", timeWatch.ElapsedMilliseconds, commonInput.Email, JsonSerializer.Serialize(input));
                throw new CodeException(httpResult.StatusCode, httpResult.RawContent);
            }
        }
        /// <summary>
        /// 创建订单
        /// </summary>
        /// <param name="input"></param>
        /// <param name="commonInput"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<OrderResDto> CreateOrder(OrdersInput input, CommonInput commonInput)
        {
            var timeWatch = new Stopwatch();
            timeWatch.Start();

            var url = "/orders?isWeChatMP=true";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
                Body = input
            };
            var httpResult = await _httpHelper.SendAndParseAsync<OrderResDto>(url, HttpMethod.Post, requestInfo);

            timeWatch.Stop();
            _logger.LogInformation($"{commonInput.Email}:创建订单接口结束,用时:{timeWatch.ElapsedMilliseconds}ms");
            await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = commonInput.Email, Action = $"创建订单接口结束",UsedTime = timeWatch.ElapsedMilliseconds });

            if (httpResult.StatusCode != 200 || httpResult.Body == null)
            {
                _logger.LogError("创建订单失败。时间:{time},用户:{email},参数:{input}", DateTime.Now.China(), commonInput.Email, JsonSerializer.Serialize(input));
                throw new CodeException(httpResult.StatusCode, httpResult.RawContent);
            }
            return httpResult.Body;
        }
        /// <summary>
        /// 创建购物车
        /// </summary>
        /// <param name="input"></param>
        /// <param name="commonInput"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<BasketDto> CreateBasket(CreateBasketInput input, CommonInput commonInput)
        {

            var url = "/baskets";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
                Body = input
            };
            var httpResult = await _httpHelper.SendAndParseAsync<BasketDto>(url, HttpMethod.Post, requestInfo);
            if (httpResult.StatusCode != 200 || httpResult.Body == null)
            {
                _logger.LogError("创建购物车失败。时间:{time},用户:{email},参数:{input}", DateTime.Now.China(), commonInput.Email, JsonSerializer.Serialize(input));
                throw new CodeException(httpResult.StatusCode, httpResult.RawContent);
            }
            return httpResult.Body;
        }
        /// <summary>
        /// 取消订单
        /// </summary>
        /// <param name="orderNo"></param>
        /// <param name="commonInput"></param>
        /// <returns></returns>
        public async Task CancelOrder(string orderNo, CommonInput commonInput)
        {
            var url = $"/orders/{orderNo}";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
                Body = new
                {
                    status = "cancelled"
                }
            };
            var httpResult = await _httpHelper.SendAsync(url, HttpMethod.Patch, requestInfo);

            if (httpResult.StatusCode != 200)
            {
                _logger.LogError("取消订单失败。时间:{time},用户:{email}", DateTime.Now.China(), commonInput.Email);
                throw new CodeException(httpResult.StatusCode, httpResult.RawContent);
            }
        }

        public async Task RemoveBasketItem(string itemId, CommonInput commonInput)
        {
            var url = $"/baskets/{commonInput.BasketId}/items/{itemId}";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
                Body = new Dictionary<string, string> { }
            };
            var httpResult = await _httpHelper.SendAsync(url, HttpMethod.Delete, requestInfo);
            if (httpResult.StatusCode != 200)
            {
                throw new CodeException(httpResult.StatusCode, httpResult.RawContent);
            }
        }

        public async Task<BasketDto> GetBasketDetail(CommonInput commonInput)
        {
            var timeWatch = new Stopwatch();
            timeWatch.Start();

            var url = $"/baskets/{commonInput.BasketId}";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
            };
            var httpResult = await _httpHelper.SendAndParseAsync<BasketDto>(url, HttpMethod.Get, requestInfo);

            timeWatch.Stop();
            await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = commonInput.Email, Action = $"查询购物车",UsedTime = timeWatch.ElapsedMilliseconds });

            if (httpResult.StatusCode != 200 || httpResult.Body == null)
            {
                _logger.LogError("获取购物车失败。用户:{email}", commonInput.Email);
                throw new CodeException(httpResult.StatusCode, httpResult.RawContent);
            }
            return httpResult.Body;
        }
        /// <summary>
        /// 设置购物车用户基本信息失败
        /// </summary>
        /// <param name="input"></param>
        /// <param name="commonInput"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task SetBasketCustomerInfo(BasketCustomerInput input, CommonInput commonInput)
        {
            var url = $"/baskets/{commonInput.BasketId}/customer";
            var requestInfo = new RequestInfo
            {
                BearerToken = commonInput.Token,
                Body = input
            };
            var httpResult = await _httpHelper.SendAsync(url, HttpMethod.Put, requestInfo);
            if (httpResult.StatusCode != 200)
            {
                _logger.LogError("设置购物车用户基本信息失败。用户:{email}", commonInput.Email);
                throw new CodeException(httpResult.StatusCode, httpResult.RawContent);
            }
        }
    }
}

